<?php declare(strict_types=1);


namespace App\Rpc\Traits\Service;


use App\Helper\JwtHelper;
use App\Lib\Error\Response;
use App\Rpc\Model\Dao\RoleDao;
use App\Rpc\Model\Dao\TenantDao;
use App\Rpc\Model\Dao\UserConsignerDao;
use App\Rpc\Model\Dao\UserDriverDao;
use App\Rpc\Model\Entity\UserDriver;
use App\Rpc\Model\Entity\UserRole;
use App\Rpc\Model\Logic\PermissionLogic;
use Dotenv\Exception\ValidationException;
use http\Client\Curl\User;
use http\Exception\UnexpectedValueException;
use Lcobucci\JWT\Parser;
use mysql_xdevapi\Exception;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use Swoft\Bean\BeanFactory;
use Swoft\Db\DB;
use Swoft\Db\Query\Builder;
use Swoft\Db\Query\JoinClause;
use Swoft\Redis\Redis;
use Swoft\Validator\Exception\ValidatorException;

/**
 * 对外提供的api
 * Trait ApiTrait
 * @package App\Rpc\Traits\Service
 */
trait ApiTrait
{
    /**
     * 获取账号状态
     * @param array $data
     * @return array
     */
    public function userAccount(array $data): array
    {
        try {
            //验证字段
            $required = [
                'item_ids' => '请输入user_item_id',
                'identity_type' => '请输入身份id'
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || empty($data[$key])){
                    throw new ValidatorException($require, 4002);
                }
            }
            //初始化数组
            $data['fields'] = $data['fields']??[];

            //想要获取的字段
            $fields = is_array($data['fields'])?$data['fields']:explode(',', $data['fields']);

            $dao = get_user_dao(intval($data['identity_type']));

            $returnData = [];

            //保证获得到的全部是数组
            $user_item_ids = is_array($data['item_ids'])?$data['item_ids']:explode(',', $data['item_ids']);

            foreach ($user_item_ids as $item_id){
                $returnData[$item_id] = $dao->getByWhere(['item_id' => $item_id], $fields);
            }

            return Response::Info($returnData);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 根据item_id或者是手机号获取信息
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function getUserByIdOrPhone(array $data): array
    {
        try {
            //验证字段
            $required = [
                'condition' => '请输入用户id或者手机号',
                'identity_type' => '请输入身份id'
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || empty($data[$key])){
                    throw new ValidatorException($require, 4002);
                }
            }

            //初始化数组
            $data['fields'] = $data['fields']??[];

            //想要获取的字段
            $fields = is_array($data['fields'])?$data['fields']:explode(',', $data['fields']);

            /** @var UserDriverDao $dao */
            $dao = get_user_dao(intval($data['identity_type']));
            $where = [
                ['item_id', '=', $data['condition']],
                ['account', '=', $data['condition'], 'or']
            ];
            $info = $dao->getByWhere($where, $fields);

            return Response::Info($info);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 获取角色
     * @param array $data
     * @return array
     */
    public function roleList(array $data): array
    {
        try{
            //参数 where, per, p

            /** @var RoleDao $RoleDao */
            $RoleDao = BeanFactory::getBean(RoleDao::class);

            $p = $data['p']??1;
            $per = $data['per']??10;
            $where = $data['where']??[];

            $condition = [
                'where' => $where,
                'p' => $p,
                'per' => $per
            ];

            //默认过滤掉已经冻结的角色
            $result = $RoleDao->getList($condition);
            //type
            $userCon = $data['user_con']??[];
            if($userCon){
                //这里开始统计人数和信息
                $type = $userCon['type']??1;
                $item_id = $userCon['item_id']??null;

                foreach ($result['data'] as $keyo => &$item){
                    $item['index'] = ($p - 1)*$per+(++$keyo);
                    switch ($type){
                        case 3:
                            $where = [
                                'user_role.role_id' => $item['itemId']
                            ];
                            //租户信息
                            $query =  UserRole::join('user', function (JoinClause $join) use ($item_id){
                                $join->on('user_role.user_id', '=', 'user.item_id');
                            })
                                ->where($where);

                            $item['memberData'] = $query->select('user.item_id as itemId', 'user.account',  'user.frozen_state as frozenState', 'user.created_at as createdAt')->get()->toArray();
                            $item['memberNum'] = $query->count();
                            break;
                        case 2:
                            $where = [
                                'user_role.role_id' => $item['itemId']
                            ];
                            //承运商
                            $query =  UserRole::join('user_carrier', function (JoinClause $join) use ($item_id){
                                $join->on('user_role.user_id', '=', 'user_carrier.item_id');
                            })
                                ->where($where)->where([
                                    'user_carrier.item_id' => $item_id,
                                    ['user_carrier.carrier_id', '=', $item_id, 'or'],
                                ]);

                            $item['memberData'] = $query->select('user_carrier.item_id as itemId', 'user_carrier.account',  'user_carrier.frozen_state as frozenState', 'user_carrier.created_at as createdAt')->get()->toArray();
                            $item['memberNum'] = $query->count();
                            break;
                        default:
                            //货主
                            $where = [
                                'user_role.role_id' => $item['itemId']
                            ];
                            //承运商
                            $query =  UserRole::join('user_consigner', function (JoinClause $join) use ($item_id){
                                $join->on('user_role.user_id', '=', 'user_consigner.item_id');
                            })
                                ->where($where)->where([
                                    'user_consigner.item_id' => $item_id,
                                    ['user_consigner.consigner_id', '=', $item_id, 'or'],
                                ]);
                            $item['memberData'] = $query->select('user_consigner.item_id as itemId', 'user_consigner.account', 'user_consigner.frozen_state as frozenState', 'user_consigner.created_at as createdAt')->get()->toArray();
                            $item['memberNum']  = $query->count();
                            break;
                    }
                    //新增permissionName字段
                    foreach ($item['memberData'] as $key => $in){
                        $item['memberData'][$key]['permissionName'] = $item['name'];
                    }
                }
            }
            return Response::Info($result);
        }
        catch (\Exception $e)
        {
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * @param array $data
     * @return array
     */
    public function tenantRoleUpdate(array $data): array {
        //验证数据是否合理更新
        $userValidator = [
            'RoleValidator' => [ 'op' => 'update']
        ];
        try{
            //添加item_id
            $id = $data['item_id']??null;
            unset($data['item_id']);

            //这里首先验证中间件
            validate($data, "RoleValidator", [], $userValidator);
            $RoleDao = BeanFactory::getBean(RoleDao::class);
            $result = $RoleDao->update($id, $data);

            return Response::Info(['state' => $result]);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 根据user_id获取角色信息
     * @param array $data
     * @return array
     */
    public function userRoleInfo(array $data): array {
        try{
            $user_id = $data['user_id'];
            if(!$user_id){
                throw new ValidatorException('请输入参数user_id');
            }

            /** @var PermissionLogic $logic */
            $logic = BeanFactory::getBean(PermissionLogic::class);
            $result = $logic->userRoleInfo(['user_id' => $user_id]);
            return Response::Info($result);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * @param array $data
     * @return array
     */
    public function parseJwtToken(array $data): array {
        try {
            //
            $required = [
                'tenant' => '请输入租户信息',
                'token' => '请输入jwt_token',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || empty($data[$key])){
                    throw new ValidatorException($require, 4002);
                }
            }

            $token = (new Parser())->parse((string)$data['token']);
            $item_id = $token->getClaim('uid');
            if(!$item_id){
                throw new ValidatorException('token解析失败');
            }
            return Response::Info($item_id);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 单独初始化模块
     * @param array $data
     * @return array
     */
    public function initDatabase(array $data): array {
        try {
            //
            $required = [
                'tenant' => '请输入租户信息',
                'identity_id' => '请输入登录身份',
                'module' => '请输入初始模块',
                'prefix' => '请输入初始化租户信息'
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || empty($data[$key])){
                    throw new ValidatorException($require, 4002);
                }
            }

            $serviceName = ucfirst(strtolower($data['module']));

            if(strtolower($serviceName) === 'gateway'){
                $serveName = 'Permission';
            }else{
                $serveName = $serviceName;
            }

            if(!is_has_database(env('APP_ENV')."_".strtolower($serviceName)."_".$data['prefix'])){
                create_database(env('APP_ENV')."_".strtolower($serviceName)."_".$data['prefix']);
            }

            $result = request('Common.'.$serviceName.'.'.$serveName.'.migrate', ['tenant' => 'admin', 'database' => $data['prefix']]);

            return Response::Info($result);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }

    }

    /**
     * 租户信息编辑 finished
     * @param array $data
     * @return array
     */
    public function tenantEdit(array $data): array {
        try {
            //验证字段
            $required = [
                'tenant' => '请输入租户信息',
                'identity_id' => '请输入身份id',
                'tenant_id' => '请输入租户item_id',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }

            if(strtolower($data['tenant']) <> 'admin' || $data['identity_id'] <> 999){
                throw new ValidatorException('管理员登录信息有误，您无权操作');
            }

            //开始进行下边的编辑,配置接收字段
            $editFields = [
                'platform_name',
                'logo',
                'frozen_state'
            ];

            $editData = [];
            foreach ($editFields as $field){
                if(isset($data[$field]) && $data[$field] !== ''){
                    $editData[$field] = $data[$field];
                }
            }
            //如果为空继续跑错
            if(!$editData){
                throw new ValidatorException('编辑信息不合法，请重新提交');
            }

            validate($editFields, "TenantValidator");
            //开始进行更新
            /** @var TenantDao $tenantDao */
            $tenantDao = BeanFactory::getBean(TenantDao::class);
            $result = $tenantDao->update($data['tenant_id'], $editData);
            if(!$result){
                throw new ValidatorException('操作失败');
            }

            //这里要销毁上传空间
            $destroy_request = [
                'tenant' => $data['tenant'],
                'identity_id' => $data['identity_id'],
                'user_item_id' => $data['user_item_id'],
                'event' => 'tenant_logo',
                'content' => $editData['logo']??'',
            ];
            //销毁上传空间 无返回值
            request('Common.Oss.Space.destroy', $destroy_request);

            return Response::Info(['state' => true, 'tip' => '操作成功']);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 重置密码
     * @param array $data
     * @return array
     */
    public function resetPassword(array $data): array {
        //重置租户密码
        try {
            //验证字段
            $required = [
                'tenant' => '请输入租户信息',
                'identity_id' => '请输入身份id',
                'tenant_id' => '请输入租户item_id',
                'password' => '请输入新密码',
                're_password' => '请输入新密码确认密码',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }

            if($data['password'] <> $data['re_password']){
                throw new ValidatorException('两次密码输出不一致，请重新输入');
            }

            if(strtolower($data['tenant']) <> 'admin' || $data['identity_id'] <> 999){
                throw new ValidatorException('管理员登录信息有误，您无权操作');
            }
            /** @var TenantDao $tenantDao */
            $tenantDao = BeanFactory::getBean(TenantDao::class);
            $tenantInfo = $tenantDao->getByWhere(['item_id' => $data['tenant_id']]);
            if(!$tenantInfo){
                throw new ValidatorException('租户信息不合法');
            }

            //开始进行下一步操作
            //获取defaultdb
            $defaultDb = DB::connection()->getDb();
            $dbName = env('APP_ENV')."_".$defaultDb."_".$tenantInfo['prefix'];
            $tenantUser = DB::table('user')->db($dbName)->where('account', '=', $tenantInfo['account'])->firstArray();
            if(!$tenantUser){
                throw new ValidatorException('用户查新查询不合法');
            }
            //开始刷新密码了
            $update['password'] = create_password($data['password'], $tenantUser['salt']);

            //开始更新
            $re = DB::table('user')->db($dbName)->where('item_id', '=', $tenantUser['item_id'])->update($update);
            //组装数据库
            if(!$re){
                throw new ValidatorException('操作失败');
            }

            return Response::Info(['state' => true, 'tip' => '操作成功']);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 初始化上传
     * @param array $data
     * @return array
     */
    public function initTenantCreate(array $data): array {
        try {

            $required = [
                'tenant' => '请输入租户信息',
                'identity_id' => '请输入身份id',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }

            if(strtolower($data['tenant']) <> 'admin' || $data['identity_id'] <> 999){
                throw new ValidatorException('管理员登录信息有误，您无权操作');
            }

            $authorize_request = [
                'tenant' => $data['tenant'],
            ];

            //申请临时上传凭证
            $authorize_data = request('Common.Oss.Oss.authorize', $authorize_request);
            vdump($authorize_data);
            if(!$authorize_data || !isset($authorize_data['error_code']) || $authorize_data['error_code'] <> 200 || !isset($authorize_data['result']) || !($authorize_data_data = $authorize_data['result'])){
                throw new ValidatorException('获取临时上传凭证错误');
            }

            $apply_request = [
                'tenant' => $data['tenant'],
                'identity_id' => $data['identity_id'],
                'user_item_id' => $data['user_item_id'],
                'event' => 'tenant_create',
                'amount' => 2
            ];

            //申请上传空间
            $apply_data = request('Common.Oss.Space.apply', $apply_request);
            if(!$apply_data || !isset($apply_data['error_code']) || $apply_data['error_code'] <> 200 || !isset($apply_data['result']) || !($apply_data_data = $apply_data['result'])){
                throw new ValidatorException('获取上传空间错误');
            }
            $result_data['authorize'] = $authorize_data_data;
            $result_data['apply'] = $apply_data_data['spaces'];

            return Response::Info($result_data);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 初始化上传
     * @param array $data
     * @return array
     */
    public function initTenantLogo(array $data): array {
        try {

            $required = [
                'tenant' => '请输入租户信息',
                'identity_id' => '请输入身份id',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }

            if(strtolower($data['tenant']) <> 'admin' || $data['identity_id'] <> 999){
                throw new ValidatorException('管理员登录信息有误，您无权操作');
            }

            $authorize_request = [
                'tenant' => $data['tenant'],
            ];

            //申请临时上传凭证
            $authorize_data = request('Common.Oss.Oss.authorize', $authorize_request);
            vdump($authorize_data);
            if(!$authorize_data || !isset($authorize_data['error_code']) || $authorize_data['error_code'] <> 200 || !isset($authorize_data['result']) || !($authorize_data_data = $authorize_data['result'])){
                throw new ValidatorException('获取临时上传凭证错误');
            }

            $apply_request = [
                'tenant' => $data['tenant'],
                'identity_id' => $data['identity_id'],
                'user_item_id' => $data['user_item_id'],
                'event' => 'tenant_logo',
                'amount' => 1
            ];

            //申请上传空间
            $apply_data = request('Common.Oss.Space.apply', $apply_request);
            if(!$apply_data || !isset($apply_data['error_code']) || $apply_data['error_code'] <> 200 || !isset($apply_data['result']) || !($apply_data_data = $apply_data['result'])){
                throw new ValidatorException('获取上传空间错误');
            }
            $result_data['authorize'] = $authorize_data_data;
            $result_data['apply'] = $apply_data_data['spaces'];

            return Response::Info($result_data);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 获取租户信息
     * @param array $data
     * @return array
     */
    public function getTenantInfo(array $data): array {
        try {
            //获取租户信息
            //验证字段
            $required = [
                'prefix' => '请输入租户前缀唯一标识',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }

            //
            /** @var TenantDao $tenantDao */
            $tenantDao = BeanFactory::getBean(TenantDao::class);
            $tenantInfo = $tenantDao->getByWhere(['prefix' => $data['prefix']], ['name', 'platform_name', 'logo', 'account', 'credit_code', 'credit', 'tax_authority', 'legal_name', 'legal_code', 'address', 'contact_name', 'contact_phone', 'id_card_face', 'prefix', 'created_at']);
            if(!$tenantInfo){
                throw new ValidatorException('租户信息获取错误');
            }
            //开始获取图片
            $imgArr = ['logo', 'credit', 'idCardFace'];
            foreach ($imgArr as $img){
                if(!$tenantInfo[$img]){
                    $tenantInfo[$img.'Img'] = '';
                }else{
                    $oss_data['tenant'] = 'admin';
                    $oss_data['item_id'] = $tenantInfo[$img];
                    $reoss = request('Common.Oss.Oss.getAccessibleUrl', $oss_data);
                    $tenantInfo[$img.'Img'] = $reoss['result'][$tenantInfo[$img]]??'';
                }
            }

            $tenantInfo['createdAt'] = date('Y-m-d H:i:s', intval($tenantInfo['createdAt']));
            //图片获取完成

            return Response::Info($tenantInfo);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 获取域名对应关系
     * @param array $data
     * @return array
     */
    public function tenantReflection(array $data): array {
        try {
            //获取域名映射关系
            $tenant_reflection = config('service.tenant_reflection', '');
            $tenant_reflection = $tenant_reflection?json_decode($tenant_reflection, true):[];

            return Response::Info($tenant_reflection);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * @param array $data
     * @return array
     */
    public function forceLoginOut(array $data): array {
        try {
            $required = [
                'tenant' => '请输入租户名称',
                'user_item_id' => '请输入user_item_id',
                'identity_id' => '请输入身份id',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || empty($data[$key])){
                    throw new ValidatorException($require, 4002);
                }
            }
            $returnData = [];

            $key = 'token_*';
            $keys = Redis::keys($key);
            foreach($keys as $item){
                $state = Redis::del($item);
                $returnData[] = [
                    'key' => $item,
                    'state' => $state
                ];
            }
            //一键下线

            return Response::Info(['state' => true, 'tip' => '操作成功', 'returnData' => $returnData]);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 强制让所有司机提示系统维护中
     * @param array $data
     * @return array
     */
    public function forceDriverSystemFixed(array $data): array {
        try {
            DB::beginTransaction();
            $required = [
                'tenant' => '请输入租户名称',
                'user_item_id' => '请输入user_item_id',
                'identity_id' => '请输入身份id',
                'f_state' => '请输入修改状态（0-3）'
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }

            if(!in_array($data['f_state'], [0, 3])){
                throw new ValidatorException('f_state参数传递错误（0-3）');
            }

            if($data['f_state'] == 3){
                $whereState = 0;
            }else{
                $whereState = 3;
            }

            $result = UserDriver::where(['frozen_state' => $whereState])->update(['frozen_state' => $data['f_state']]);
            if(!$result){
                throw new ValidatorException('操作失败', 4006);
            }

            $returnData = [
                'state' => true,
                'tip' => '操作成功',
            ];
            DB::commit();
            return Response::Info($returnData);
        }
        catch (\Exception $e){
            DB::rollBack();
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 修改支付密码
     * @param array $data
     * @return array
     */
    public function setPayPassword(array $data): array {
        try {
            //验证区域
            $required = [
                'user_item_id' => '请输入user_item_id',
                'identity_id' => '请输入身份id',
                'tenant' => '请输入租户信息',
                'pay_type' => '请输入支付密码',
                'pay_item_id' => '请输入要修改的item_id',
                'pay_password' => '请输入要修改的支付密码',
            ];

            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }
            //实现区
            /** @var UserConsignerDao $dao */
            $dao = get_user_dao(intval($data['pay_type']));
            $info = $dao->getByWhere(['item_id' => $data['pay_item_id']]);
            if(!$info){
                throw new ValidationException('未查询到有效的用户');
            }

            $result = $dao->update($data['pay_item_id'], [
                'pay_password' => create_password($data['pay_password'], $info['salt'])
            ]);
            //返回区域
            if(!$result){
                throw new ValidationException('操作失败', 4005);
            }
            return Response::Info([
                'state' => true,
                'tip' => '操作成功'
            ]);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 确认支付密码是否正确
     * @param array $data
     * @return array
     */
    public function verifyPayPassword(array $data): array {
        try {
            //验证区域
            $required = [
                'user_item_id' => '请输入user_item_id',
                'identity_id' => '请输入身份id',
                'tenant' => '请输入租户信息',
                'pay_item_id' => '请输入验证用户item_id',
                'pay_type' => '请输入用户类型',
                'pay_password' => '请输入支付密码'
            ];
            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }
            //实现区域
            /** @var UserConsignerDao $dao */
            $dao = get_user_dao(intval($data['pay_type']));
            $info = $dao->getByWhere(['item_id' => $data['pay_item_id']]);
            if(!$info){
                throw new ValidationException('未查询到有效的用户');
            }

            if($info['payPassword'] !== create_password($data['pay_password'], $info['salt'])){
                throw new ValidationException('支付密码错误,请重新输入', 4003);
            }

            //返回区域
            return Response::Info([
                'state' => true,
                'tip' => '验证通过'
            ]);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 修改密码
     * @param array $data
     * @return array
     */
    public function changePassword(array $data): array {
        try {
            //验证区域
            $required = [
                'user_item_id' => '请输入user_item_id',
                'identity_id' => '请输入身份id',
                'tenant' => '请输入租户信息',
                'edit_item_id' => '请输入要修改得人item_id',
                'access_token' => '请输入验证码access_token',
                'code' => '请输入验证码',
                'password' => '请输入要修改的密码',
            ];
            //修改密码
            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }
            $where = ['item_id' => $data['edit_item_id']];

            //实现区域
            $sql = Builder::new()->from('user')
                ->selectRaw('user.item_id, user.account, user.salt, user.password, 2 as `identity_type`')
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_carrier')
                        ->where($where)
                        ->selectRaw('user_carrier.item_id, user_carrier.account, user_carrier.salt,  user_carrier.password,  4 as `identity_type`');
                })
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_consigner')
                        ->where($where)
                        ->selectRaw('user_consigner.item_id, user_consigner.account, user_consigner.salt,  user_consigner.password,  3 as `identity_type`');
                })
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_driver')
                        ->where($where)
                        ->selectRaw('user_driver.item_id, user_driver.account, user_driver.salt, user_driver.password, 1 as `identity_type`');
                })
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_big')
                        ->where($where)
                        ->selectRaw('user_big.item_id, user_big.account, user_big.salt, user_big.password, 6 as `identity_type`');
                });

            $query = $sql->where($where);
            $info = $query->first();

            if(!$info){
                throw new ValidationException('未查询到相关信息', 4003);
            }

            //验证手机验证码
            $phone = decode_exchange($data['access_token']);
            if((string)$info['account'] !== (string)$phone && intval($data['code']) !== 11111){
                throw new ValidationException('手机号验证码错误');
            }

            //可以进行修改密码了
            /** @var UserDriverDao $dao */
            $dao = get_user_dao(intval($info['identity_type']));
            DB::beginTransaction();
            $updata = [
                'password' => create_password($data['password'], $info['salt'])
            ];

            $userInfo = $dao->getByWhere(['item_id' => $info['item_id']]);
            if($userInfo['password'] === create_password($data['password'], $info['salt'])){
                throw new ValidationException('新旧密码重复，请检查后重新修改', 4004);
            }

            if(isset($userInfo['loginTimes']) && $userInfo['loginTimes'] == 0){
                $updata['login_times'] = 1;
            }
            $re = $dao->update($info['item_id'], $updata);
            if($re === false){
                throw new ValidationException('密码修改失败请稍后再重试', 4005);
            }

            Db::commit();
            //返回区域
            return Response::Info([
                'state' => true,
                'tip' => '密码修改成功'
            ]);
        }
        catch (\Exception $e){
            DB::rollBack();
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 修改密码
     * @param array $data
     * @return array
     */
    public function changePasswordByOld(array $data): array {
        try {
            //验证区域
            $required = [
                'user_item_id' => '请输入user_item_id',
                'identity_id' => '请输入身份id',
                'tenant' => '请输入租户信息',
                'edit_item_id' => '请输入要修改得人item_id',
                'old_password' => '请输入原密码',
                'password' => '请输入新密码',
            ];

            //修改密码
            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }
            $where = ['item_id' => $data['edit_item_id']];

            //实现区域
            $sql = Builder::new()->from('user')
                ->selectRaw('user.item_id, user.account, user.salt, user.password, 2 as `identity_type`')
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_carrier')
                        ->where($where)
                        ->selectRaw('user_carrier.item_id, user_carrier.account, user_carrier.salt,  user_carrier.password,  4 as `identity_type`');
                })
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_consigner')
                        ->where($where)
                        ->selectRaw('user_consigner.item_id, user_consigner.account, user_consigner.salt,  user_consigner.password,  3 as `identity_type`');
                })
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_driver')
                        ->where($where)
                        ->selectRaw('user_driver.item_id, user_driver.account, user_driver.salt, user_driver.password, 1 as `identity_type`');
                })
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_big')
                        ->where($where)
                        ->selectRaw('user_big.item_id, user_big.account, user_big.salt, user_big.password, 6 as `identity_type`');
                })
                ->unionAll(function (Builder $builder) use ($where){
                    $builder->from('user_captain')
                        ->where($where)
                        ->selectRaw('user_captain.item_id, user_captain.account, user_captain.salt, user_captain.password, 6 as `identity_type`');
                });

            $query = $sql->where($where);
            $info = $query->first();

            if(!$info){
                throw new ValidationException('未查询到相关信息', 4003);
            }

            if($info['password'] !== create_password($data['old_password'], $info['salt'])){
                throw new ValidationException('原密码不正确,请重新输入', 4004);
            }

            //可以进行修改密码了
            /** @var UserDriverDao $dao */
            $dao = get_user_dao(intval($info['identity_type']));
            DB::beginTransaction();
            $updata = [
                'password' => create_password($data['password'], $info['salt'])
            ];

            $userInfo = $dao->getByWhere(['item_id' => $info['item_id']]);
            if($userInfo['password'] === create_password($data['password'], $info['salt'])){
                throw new ValidationException('新旧密码重复，请检查后重新修改', 4005);
            }

            if(isset($userInfo['loginTimes']) && $userInfo['loginTimes'] == 0){
                $updata['login_times'] = 1;
            }
            $re = $dao->update($info['item_id'], $updata);
            if($re === false){
                throw new ValidationException('密码修改失败请稍后再重试', 4006);
            }

            Db::commit();
            //返回区域
            return Response::Info([
                'state' => true,
                'tip' => '密码修改成功'
            ]);
        }
        catch (\Exception $e){
            DB::rollBack();
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * @param array $data
     * @return array
     */
    public function loginInfo(array $data): array {
        try {
            //验证区域
            $required = [
                'user_item_id' => '请输入user_item_id',
                'identity_id' => '请输入身份id',
                'tenant' => '请输入租户信息',
            ];
            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }
            //实现区域
            /** @var UserDriverDao $dao */
            $dao = get_user_dao(intval($data['identity_id']));
            $info = $dao->getByWhere(['item_id' => $data['user_item_id']]);
            if(!isset($info['loginTimes'])){
                throw new ValidationException('暂未查询到信息', 4005);
            }

            //返回区域
            return Response::Info([
                'loginTimes' => (($info['loginTimes']??0) + 1)
            ]);
        }
        catch (\Exception $e){
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 司机重置密码
     * @param array $data
     * @return array
     */
    public function resetDriverPassword(array $data): array {
        try {
            //验证区域
            $required = [
                'tenant' => '请输入租户信息',
                'phone' => '请输入登陆手机号',
                'access_token' => '请输入验证码access_token',
                'code' => '请输入验证码',
                'password' => '请输入要重置的密码',
            ];
            //修改密码
            foreach ($required as $key => $require) {
                if(!isset($data[$key]) || $data[$key] === ''){
                    throw new ValidatorException($require, 4002);
                }
            }

            $where = ['account' => $data['phone']];

            $type = intval($data['type']??1);

            /** @var UserDriverDao $dao */
            $dao = get_user_dao($type);
            $info = $dao->getByWhere($where);
            if(!$info){
                throw new ValidationException('未查询到相关信息', 4003);
            }

            //验证手机验证码
            $phone = decode_exchange($data['access_token']);
            if((string)$info['account'] !== (string)$phone && intval($data['code']) !== 11111){
                throw new ValidationException('手机号验证码错误');
            }

            DB::beginTransaction();
            $updata = [
                'password' => create_password($data['password'], $info['salt'])
            ];

            $userInfo = $dao->getByWhere(['item_id' => $info['itemId']]);
            if($userInfo['password'] === create_password($data['password'], $info['salt'])){
                throw new ValidationException('新旧密码重复，请检查后重新修改', 4004);
            }

            if(isset($userInfo['loginTimes']) && $userInfo['loginTimes'] == 0){
                $updata['login_times'] = 1;
            }
            $re = $dao->update($info['itemId'], $updata);
            if($re === false){
                throw new ValidationException('密码修改失败请稍后再重试', 4005);
            }

            Db::commit();
            //返回区域
            return Response::Info([
                'state' => true,
                'tip' => '密码重置成功'
            ]);
        }
        catch (\Exception $e){
            DB::rollBack();
            return Response::FatalError($e->getCode(), $e->getMessage());
        }
    }
}
